<template>
    <el-row class="lucidity-note-aside-toolbar-box box-bottom-shadow">
        <el-col :span="16" class="toolbar-box-search">
            <el-input
                v-model="searchText" 
                placeholder="输入查找内容" 
                maxlength="30" 
                @change="search"
                clearable />
        </el-col>
        <el-col :span="8" class="toolbar-box-icons">
            <el-icon class="" title="远程同步" :class="loading" @click="remoteSync()"><Refresh /></el-icon>
            <el-icon class="toolbar-op-icon" title="新增节点" @click="newRootFile()"><DocumentAdd /></el-icon>
            <el-icon class="toolbar-op-icon" title="新增分类" @click="newRootFolder()"><FolderAdd /></el-icon>
            <!-- <el-icon class="toolbar-op-icon" title="展开节点"><Expand /></el-icon>
            <el-icon class="toolbar-op-icon" title="收缩节点"><Fold /></el-icon> -->
        </el-col>
    </el-row>
    <el-row class="lucidity-note-aside-tree-box box-bottom-shadow">
        <el-tree class="lucidity-note-aside-notetree" 
            ref="notetree"
            :data="treedata" 
            :default-expanded-keys="expandNodes"
            :highlight-current="true"
            node-key="id"
            :expand-on-click-node="false"
            :filter-node-method="filterNode"
            @node-click="nodeClickHandler"
            >
            <!-- 树节点插槽 -->
            <template #default="{ node, data }">
                <!-- 可编辑状态 -->
                <span class="lucidity-note-custom-tree-node" v-if="data.editable">
                    <el-input class="lucidity-note-custom-edit-input"
                        v-model="editorNodeText" 
                        autofocus
                        size="small"
                        placeholder="请输入文件或文件夹名称"
                        @blur.stop="nodeEidtorHandler(node, data)"
                        @keyup.enter.native="nodeEidtorHandler(node, data)"></el-input>
                </span>
                
                <!-- 非编辑状态 -->
                <span class="lucidity-note-custom-tree-node" v-else>
                    <el-icon v-if="!data.children"><Document /></el-icon>
                    <el-icon v-else-if="node.expanded"><FolderOpened /></el-icon>
                    <el-icon v-else><Folder /></el-icon>
                    <span class="lucidity-note-custom-tree-node-info" :title="node.label">{{ node.label }}</span>

                    <el-dropdown type="primary" size="small">
                        <el-icon class="node-op-icon"><ArrowDown /></el-icon>
                        <template #dropdown>
                            <el-dropdown-menu>
                                <el-dropdown-item @click="renameNodeHandler(node, data)">
                                    <span><el-icon><EditPen /></el-icon></span>
                                    <span>重命名</span>
                                </el-dropdown-item>
                                <el-dropdown-item @click="newFileNodeHandler(node, data)" v-if="data.isdir">
                                    <span><el-icon><DocumentAdd /></el-icon></span>
                                    <span>新增文件</span>
                                </el-dropdown-item>
                                <el-dropdown-item @click="newFolderNodeHandler(node, data)"  v-if="data.isdir">
                                    <span><el-icon><FolderAdd /></el-icon></span>
                                    <span>新增下级目录</span>
                                </el-dropdown-item>
                                <el-dropdown-item @click="deleteNodeHandler(node, data)">
                                    <span><el-icon><Delete /></el-icon></span>
                                    <span>删除当前节点</span>
                                </el-dropdown-item>
                            </el-dropdown-menu>
                        </template>
                </el-dropdown>
                </span>
            </template>
        </el-tree>
    </el-row>
</template>

<script>
    import {ref, reactive, toRefs, onMounted} from "vue";
    export default ({
        props: ['appTransfer'],

        methods: {
            search: function(value, number) {
                this.$refs.notetree.filter(value)
            }
        },

        setup(props, {emit}) {
            const LUCIDITY_NOTE_ASIDE_DATASET = reactive({
                searchText: "",
                isShowOpPanel: false,
                editorNodeText: "",
                treedata: [],
                // 设置展开节点
                expandNodes: [],
                notebookId: props.appTransfer.currNotebook ? props.appTransfer.currNotebook.id : undefined,
                loading: null,
            });

            /**
             * 节点点击时间处理
             * @param {*} data 
             * @param {*} node 
             * @param {*} component 
             * @param {*} event 
             */
            const nodeClickHandler = (data, node, component, event) => {
                // 如果当前节点处于编辑状态，则点击事件不需要触发
                if (data.editable || data.isdir) return;
                // todo 点击文件打开文件显示在编辑栏框中
                LucidityNoteApp.$mitt.emit(LucidityNoteApp.COMMANDS.openFile, data)
            };

            /**
             * 节点重命名
             * @param {*} node 节点对象
             * @param {*} data 节点数据
             */
            const renameNodeHandler = (node, data) => {
                LUCIDITY_NOTE_ASIDE_DATASET.editorNodeText = node.label
                // 设置为编辑状态
                if (!data.editable) {
                    data.editable = true
                }
            };

            /**
             * 新增文件节点
             * @param {*} node 节点对象
             * @param {*} data 节点数据
             */
            const newFileNodeHandler = (node, data) => {
                ElementPlus.ElMessageBox.prompt(`将在[${data.label}]目录下新增子文件，请输入文件名称`, '新增文件', {
                    confirmButtonText: '新增',
                    cancelButtonText: '取消新增',
                    inputPattern: /[a-zA-Z0-9\u4e00-\u9fa5]+\.{1}[a-zA-Z0-9.]+$/,
                    inputErrorMessage: '非法文件名称'
                }).then((params) => {
                    LucidityNoteApp.Helper.net.post(
                        "/notetree/new",
                        {notebookid: data.notebookid, parentid: data.id, name: params.value, types: "file"},
                        (response) => {                            
                            LUCIDITY_NOTE_ASIDE_DATASET.treedata = []
                            LUCIDITY_NOTE_ASIDE_DATASET.treedata.push.apply(LUCIDITY_NOTE_ASIDE_DATASET.treedata, response.data)

                            // 展开删除节点的上层目录节点
                            LUCIDITY_NOTE_ASIDE_DATASET.expandNodes = []
                            LUCIDITY_NOTE_ASIDE_DATASET.expandNodes.push(data.id)

                            ElementPlus.ElMessage({
                                type: 'success',
                                message: `[${data.label}]目录下添加子目录 [${params.value}] 成功.`
                            })

                            // 打开编辑框
                            LucidityNoteApp.$mitt.emit(LucidityNoteApp.COMMANDS.openFile, response.extdata)
                        },
                        (err) => {
                            ElementPlus.ElMessage.error(err.message);
                        }
                    );
                })
            };

            /**
             * 新增目录节点
             * @param {*} node 节点对象
             * @param {*} data 节点数据
             */
            const newFolderNodeHandler = (node, data) => {
                ElementPlus.ElMessageBox.prompt(`将在[${data.label}]目录下新增子文件夹，请输入文件夹名称`, '新增文件夹', {
                    confirmButtonText: '新增',
                    cancelButtonText: '取消新增',
                    inputPattern: /[a-zA-Z0-9\u4e00-\u9fa5]+$/,  // 正则表达式不包含：@ \ / " ' . \s 等符号
                    inputErrorMessage: '非法文件夹名称'
                }).then((params) => {
                    LucidityNoteApp.Helper.net.post(
                        "/notetree/new",
                        {notebookid: data.notebookid, parentid: data.id, name: params.value, types: "folder"},
                        (response) => {                            
                            LUCIDITY_NOTE_ASIDE_DATASET.treedata = []
                            LUCIDITY_NOTE_ASIDE_DATASET.treedata.push.apply(LUCIDITY_NOTE_ASIDE_DATASET.treedata, response.data)

                            // 展开删除节点的上层目录节点
                            LUCIDITY_NOTE_ASIDE_DATASET.expandNodes = []
                            LUCIDITY_NOTE_ASIDE_DATASET.expandNodes.push(data.id)

                            ElementPlus.ElMessage({
                                type: 'success',
                                message: `[${data.label}]目录下添加子目录 [${params.value}] 成功.`
                            })
                        },
                        (err) => {
                            ElementPlus.ElMessage.error(err.message);
                        }
                    );
                })
            };

            /**
             * 删除节点
             * @param {*} node 节点对象
             * @param {*} data 节点数据删除
             */
            const deleteNodeHandler = (node, data) => {
                ElementPlus.ElMessageBox({
                    title: '操作确认',
                    message: data.isdir ? `确定要删除${data.label}文件夹，及其下所有的文件吗？` : `确定要删除${data.label}文件吗?`,
                    showCancelButton: true,
                    confirmButtonText: '确定',
                    cancelButtonText: '取消',
                }).then((params) => {
                    if (params === 'confirm') { 
                        LucidityNoteApp.Helper.net.delete(
                            "/notetree/delete/" + data.notebookid + "/" + data.id,
                            null,
                            (response) => {
                                LUCIDITY_NOTE_ASIDE_DATASET.treedata = []
                                LUCIDITY_NOTE_ASIDE_DATASET.treedata.push.apply(LUCIDITY_NOTE_ASIDE_DATASET.treedata, response.data)
                                ElementPlus.ElMessage({type:"success", message: response.message});
                            },
                            (err) => {
                                ElementPlus.ElMessage.error(err.message);
                            },
                            () => {
                                // 展开删除节点的上层目录节点
                                LUCIDITY_NOTE_ASIDE_DATASET.expandNodes = []
                                LUCIDITY_NOTE_ASIDE_DATASET.expandNodes.push(data.parent)
                            }
                        );
                    }
                })
            };

            /**
             * 重命名编辑处理
             * @param {*} node 节点对象
             * @param {*} data 节点数据删除
             */
            const nodeEidtorHandler = (node, data) => {
                var newVal = LUCIDITY_NOTE_ASIDE_DATASET.editorNodeText;
                if (newVal !== data.label) {
                    // 更新后台数据
                    LucidityNoteApp.Helper.net.put(
                        "/notetree/rename",
                        {notebookid: data.notebookid, newname: newVal, noteid: data.id},
                        (response) => {
                            // 后台数据更新成功之后，设置值
                            node.data = response.data;
                            data = response.data;
                            ElementPlus.ElMessage({type:"success", message: response.message})
                        },
                        (err) => {ElementPlus.ElMessage.error(err.message)},
                        () => {
                            // 退出编辑状态
                            if (data.editable) {
                                data.editable = false
                            }
                        }
                    );
                }
            };

            /**
             * 树节点根据文本过滤
             * @param {string} value 过滤文本
             * @param {tree} tree 树对象
             */

            const filterNode = (value, tree, node) => {
                if (!value) return true
                // todo 之后升级功能将其改造成如果是父节点那么也将其节点展示出来
                return tree.label.includes(value)
            };

            /**
             * 新增根节点文件
             */
            const newRootFile = () => {
                ElementPlus.ElMessageBox.prompt("将在当前笔记本下添加新的根文件", '新增文件', {
                    confirmButtonText: '新增',
                    cancelButtonText: '取消新增',
                    inputPattern: /[a-zA-Z0-9\u4e00-\u9fa5]+\.{1}[a-zA-Z0-9.]+$/,
                    inputErrorMessage: '非法文件名称'
                }).then((params) => {
                    var type = "file";
                    LucidityNoteApp.Helper.net.post(
                        `/notetree/new/root/${LUCIDITY_NOTE_ASIDE_DATASET.notebookId}/${params.value}/${type}`,
                        null,
                        (response) => {
                            LUCIDITY_NOTE_ASIDE_DATASET.treedata = []
                            LUCIDITY_NOTE_ASIDE_DATASET.treedata.push.apply(LUCIDITY_NOTE_ASIDE_DATASET.treedata, response.data)
                            ElementPlus.ElMessage({type:"success", message: response.message});
                            // 打开编辑框
                            LucidityNoteApp.$mitt.emit(LucidityNoteApp.COMMANDS.openFile, response.extdata)
                        },
                        (err) => {
                            ElementPlus.ElMessage.error(err.message);
                        }
                    );
                });
            };

            /**
             * 新增根节点目录
             */
            const newRootFolder = () => {
                ElementPlus.ElMessageBox.prompt("将在当前笔记本下添加新的根文件夹", '新增文件夹', {
                    confirmButtonText: '新增',
                    cancelButtonText: '取消新增',
                    inputPattern: /[a-zA-Z0-9\u4e00-\u9fa5]+$/,  // 正则表达式不包含：@ \ / " ' . \s 等符号
                    inputErrorMessage: '非法文件夹名称'
                }).then((params) => {
                    var type = "floder";
                    LucidityNoteApp.Helper.net.post(
                        `/notetree/new/root/${LUCIDITY_NOTE_ASIDE_DATASET.notebookId}/${params.value}/${type}`,
                        null,
                        (response) => {
                            LUCIDITY_NOTE_ASIDE_DATASET.treedata = []
                            LUCIDITY_NOTE_ASIDE_DATASET.treedata.push.apply(LUCIDITY_NOTE_ASIDE_DATASET.treedata, response.data)
                            ElementPlus.ElMessage({type:"success", message: response.message});
                        },
                        (err) => {
                            ElementPlus.ElMessage.error(err.message);
                        }
                    );
                });
            };

            const remoteSync = () => {
                emit("load-overlay", {loading:true, loadText: "正在远端仓库和本地同步中,请稍候..."});
                LUCIDITY_NOTE_ASIDE_DATASET.loading = "is-loading"
                LucidityNoteApp.Helper.net.put(
                    `/remote/sync/${LUCIDITY_NOTE_ASIDE_DATASET.notebookId}`,
                    null,
                    (response) => {
                        LUCIDITY_NOTE_ASIDE_DATASET.treedata = response.data
                        ElementPlus.ElMessage({
                            type: "success",
                            message: response.message
                        })
                    },
                    (err) => {ElementPlus.ElMessage.error(err.message)},
                    () => {
                        emit("load-overlay", {loading:false, loadText: ""});
                        LUCIDITY_NOTE_ASIDE_DATASET.loading = "";
                    }
                );
            };

            onMounted(() => {
                (function() {
                    if (!LUCIDITY_NOTE_ASIDE_DATASET.notebookId) return;
                    LucidityNoteApp.Helper.net.get(
                        `/notetree/${LUCIDITY_NOTE_ASIDE_DATASET.notebookId}`,
                        null,
                        (response) => {
                            LUCIDITY_NOTE_ASIDE_DATASET.treedata = response.data
                        },
                        (err) => {ElementPlus.ElMessage.error(err.message)}
                    );
                })();

                // 监听加载树指令触发
                LucidityNoteApp.$mitt.on(LucidityNoteApp.COMMANDS.loadTree, (notebook) => {
                    LUCIDITY_NOTE_ASIDE_DATASET.notebookId = notebook.id
                    LucidityNoteApp.Helper.net.get(
                        `/notetree/${notebook.id}`,
                        null,
                        (response) => {
                            LUCIDITY_NOTE_ASIDE_DATASET.treedata = response.data
                        },
                        (err) => {ElementPlus.ElMessage.error(err.message)}
                    );
                });
            });

            return {
                ...toRefs(LUCIDITY_NOTE_ASIDE_DATASET),
                nodeClickHandler,
                renameNodeHandler,
                newFileNodeHandler,
                newFolderNodeHandler,
                deleteNodeHandler,
                nodeEidtorHandler,
                filterNode,
                newRootFile,
                newRootFolder,
                remoteSync
            }
        },
    })
</script>

<style scoped>
    .lucidity-note-aside-toolbar-box {
        height: 2rem;
        width: calc(var(--lucidity-note-full-width) - 1rem);
        margin: .5rem;
        border-radius: 2rem;
        text-align: right;
        background: var(--lucidity-note-app-aside-bkcolor);
    }

    .toolbar-box-icons {
        padding-right: 1rem;
        display: flex;
        align-items: center;
        justify-content: flex-end;
        cursor: pointer;
    }

    .toolbar-op-icon {
        padding-left: .5rem;
    }

    .lucidity-note-aside-tree-box {
        margin: 0rem .5rem .5rem .5rem;
        width: calc(var(--lucidity-note-full-width) - 1rem);
        height: calc(var(--lucidity-note-full-height) - 3.5rem);
        overflow-y: auto;
        border-radius: 3px;
    }

    .lucidity-note-aside-notetree {
        width: var(--lucidity-note-full-width);
        max-height: calc(var(--lucidity-note-full-height) - 1px);
        border-radius: .2rem;
        background: var(--lucidity-note-app-aside-bkcolor);
        color: var(--lucidity-note-app-adside-font-color);
    }

    .toolbar-box-search {
        padding: 0rem 1rem;
    }


    .lucidity-note-custom-tree-node {
        flex: 1;
        display: flex;
        align-items: center;
        justify-content: space-between;
        font-size: 14px;
        padding-right: 8px;
        width: calc(var(--lucidity-note-full-width) - 36px);
        height: 100%;
    }

    .lucidity-note-custom-tree-node-info {
        width: calc(var(--lucidity-note-full-width) - 2rem);
        word-wrap: break-word;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        display: block;
        height: 100%;
        line-height: 30px;
    }

    .lucidity-note-custom-tree-node > span:last-child {
        width: auto;
        padding: 0rem .1rem;
    }

    .lucidity-note-custom-edit-input {
        background: var(--lucidity-note-app-aside-bkcolor);
    }

    .toolbar-op-icon:hover, .node-op-icon:hover {
        color: var(--lucidity-note-common-hover-color);
    }

</style>

<style>
    .lucidity-note-aside-tree-box .el-tree-node {
        width: var(--lucidity-note-full-width);
    }

    .lucidity-note-aside-tree-box .el-input__wrapper {
        background-color: var(--lucidity-note-aside-panel-filetree-search-bkcolor);
    }

    .lucidity-note-aside-tree-box .el-tree-node:focus>.el-tree-node__content {
        background: var(--lucidity-note-app-aside-bkcolor);
    }

    .toolbar-box-search .el-input__wrapper {
        background: transparent;
        box-shadow: none;

    }

    .toolbar-box-search .el-input__wrapper.is-focus {
        box-shadow: none;
    }

    .lucidity-note-custom-edit-input .el-input__wrapper {
        background: transparent;
        box-shadow: none;

    }

    .lucidity-note-custom-edit-input .el-input__wrapper.is-focus {
        box-shadow: none;
    }
</style>